import MessageKit
import InputBarAccessoryView
import Kingfisher
import MapKit
import UIKit
import SwiftEventBus

// MARK: - AdvancedExampleViewController

final class AdvancedExampleViewController: BasicChatViewController,UIContextMenuInteractionDelegate,VoiceOverlayDelegate {
    let voiceOverlayController = VoiceOverlayController()
    func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
        return UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { (elements) -> UIMenu? in
            let favoriteAction = UIAction(title: "喜欢", image: UIImage(systemName: "heart.fill"), state: .off) { (action) in
                
            }
            let shareAction = UIAction(title: "分享", image: UIImage(systemName: "square.and.arrow.up.fill"), state: .off) { (action) in
                
            }
            let deleteAction = UIAction(title: "删除", image: UIImage(systemName: "trash.fill"),
                                        attributes: [.destructive], state: .off) { (action) in
                
            }
            return UIMenu(title: "菜单", children: [favoriteAction, shareAction, deleteAction])
        }
    }
    
    // MARK: Public
    
    // MARK: - UICollectionViewDataSource
    
    public override func collectionView(
        _ collectionView: UICollectionView,
        cellForItemAt indexPath: IndexPath)
    -> UICollectionViewCell
    {
        guard let messagesDataSource = messagesCollectionView.messagesDataSource else {
            fatalError("Ouch. nil data source for messages")
        }
        
        // Very important to check this when overriding `cellForItemAt`
        // Super method will handle returning the typing indicator cell
        guard !isSectionReservedForTypingIndicator(indexPath.section) else {
            return super.collectionView(collectionView, cellForItemAt: indexPath)
        }
        
        let message = messagesDataSource.messageForItem(at: indexPath, in: messagesCollectionView)
        if case .custom = message.kind {
            let cell = messagesCollectionView.dequeueReusableCell(CustomCell.self, for: indexPath)
            cell.configure(with: message, at: indexPath, and: messagesCollectionView)
            return cell
        }
        return super.collectionView(collectionView, cellForItemAt: indexPath)
    }
    
    // MARK: Internal
    
    let outgoingAvatarOverlap: CGFloat = 17.5
    
    override func viewDidLoad() {
        messagesCollectionView = MessagesCollectionView(frame: .zero, collectionViewLayout: CustomMessagesFlowLayout())
        messagesCollectionView.register(CustomCell.self)
        
        super.viewDidLoad()
        
        voiceOverlayController.delegate = self
        
        // If you want to start recording as soon as modal view pops up, change to true
        voiceOverlayController.settings.autoStart = true
        voiceOverlayController.settings.autoStop = false
        voiceOverlayController.settings.showResultScreen = false
//        ((voiceOverlayController.inputViewController?.speechController) as! SpeechController).setLocale(Locale(identifier: "zh-CN"))
    }
    
    
    
    override func configureMessageCollectionView() {
        super.configureMessageCollectionView()
        
        let layout = messagesCollectionView.collectionViewLayout as? MessagesCollectionViewFlowLayout
        layout?.sectionInset = UIEdgeInsets(top: 1, left: 8, bottom: 1, right: 8)
        
        // Hide the outgoing avatar and adjust the label alignment to line up with the messages
        layout?.setMessageOutgoingAvatarSize(.zero)
        layout?
            .setMessageOutgoingMessageTopLabelAlignment(LabelAlignment(
                textAlignment: .right,
                textInsets: UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 8)))
        layout?
            .setMessageOutgoingMessageBottomLabelAlignment(LabelAlignment(
                textAlignment: .right,
                textInsets: UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 8)))
        
        // Set outgoing avatar to overlap with the message bubble
        layout?
            .setMessageIncomingMessageTopLabelAlignment(LabelAlignment(
                textAlignment: .left,
                textInsets: UIEdgeInsets(top: 0, left: 18, bottom: outgoingAvatarOverlap, right: 0)))
        layout?.setMessageIncomingAvatarSize(CGSize(width: 30, height: 30))
        layout?
            .setMessageIncomingMessagePadding(UIEdgeInsets(
                top: -outgoingAvatarOverlap,
                left: -18,
                bottom: outgoingAvatarOverlap,
                right: 18))
        
        layout?.setMessageIncomingAccessoryViewSize(CGSize(width: 30, height: 30))
        layout?.setMessageIncomingAccessoryViewPadding(HorizontalEdgeInsets(left: 8, right: 0))
        layout?.setMessageIncomingAccessoryViewPosition(.messageBottom)
        layout?.setMessageOutgoingAccessoryViewSize(CGSize(width: 30, height: 30))
        layout?.setMessageOutgoingAccessoryViewPadding(HorizontalEdgeInsets(left: 0, right: 8))
        
        messagesCollectionView.messagesLayoutDelegate = self
        messagesCollectionView.messagesDisplayDelegate = self
    }
    
    
    
    override func configureMessageInputBar() {
        super.configureMessageInputBar()
        
        messageInputBar.inputTextView.textContainerInset = UIEdgeInsets(top: 8, left: 16, bottom: 8, right: 36)
        messageInputBar.inputTextView.placeholderLabelInsets = UIEdgeInsets(top: 8, left: 20, bottom: 8, right: 36)
        messageInputBar.inputTextView.layer.borderColor = primaryColor.cgColor
        messageInputBar.inputTextView.layer.borderWidth = 0
        messageInputBar.inputTextView.layer.cornerRadius = 16.0
        messageInputBar.inputTextView.layer.masksToBounds = true
        //    messageInputBar.inputTextView.scrollIndicatorInsets = UIEdgeInsets(top: 8, left: 0, bottom: 8, right: 0)
        configureInputBarItems()
        //    inputBarType = .custom(messageInputBar)
        
//        messageInputBar.inputTextView.text = "我是一个互联网行业从业者，今年28岁，大专，想要安稳的生活，请帮我定制一套适合未来10年的职业规划。"
        
    }
    
    // MARK: - Helpers
    
    func isTimeLabelVisible(at indexPath: IndexPath) -> Bool {
        indexPath.section % 3 == 0 && !isPreviousMessageSameSender(at: indexPath)
    }
    
    func isPreviousMessageSameSender(at indexPath: IndexPath) -> Bool {
        guard indexPath.section - 1 >= 0 else { return false }
        return messageList[indexPath.section].user == messageList[indexPath.section - 1].user
    }
    
    func isNextMessageSameSender(at indexPath: IndexPath) -> Bool {
        guard indexPath.section + 1 < messageList.count else { return false }
        return messageList[indexPath.section].user == messageList[indexPath.section + 1].user
    }
    
    func setTypingIndicatorViewHidden(_ isHidden: Bool, animated: Bool, performUpdates updates: (() -> Void)? = nil) {
        //    updateTitleView(title: "MessageKit", subtitle: isHidden ? "2 Online" : "Typing...")
        setTypingIndicatorViewHidden(isHidden, animated: animated, whilePerforming: updates) { [weak self] success in
            if success, self?.isLastSectionVisible() == true {
                self?.messagesCollectionView.scrollToLastItem(animated: true)
            }
        }
    }
    
    // MARK: - MessagesDataSource
    
    override func cellTopLabelAttributedText(for message: MessageType, at indexPath: IndexPath) -> NSAttributedString? {
        if isTimeLabelVisible(at: indexPath) {
            return NSAttributedString(
                string: MessageKitDateFormatter.shared.string(from: message.sentDate),
                attributes: [
                    NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 10),
                    NSAttributedString.Key.foregroundColor: UIColor.white.withAlphaComponent(0.6       ),
                ])
        }
        return nil
    }
    
    override func messageTopLabelAttributedText(for message: MessageType, at indexPath: IndexPath) -> NSAttributedString? {
        
        return nil
    }
    
    override func messageBottomLabelAttributedText(for message: MessageType, at indexPath: IndexPath) -> NSAttributedString? {
        
        return nil
    }
    
    
    // Second way to listen to recording through delegate
    func recording(text: String?, final: Bool?, error: Error?) {
      if let error = error {
        print("delegate: error \(error)")
      }
      
      if error == nil,let text = text ,text != "" {
          messageInputBar.inputTextView.text = text
        print("text:\(text)")
      }
    }
    
    // MARK: Private
    
    private func configureInputBarItems() {
        
        let refresh = InputBarButtonItem()
            .configure {
                $0.spacing = .fixed(10)
                $0.tintColor = UIColor(white: 1, alpha: 0.3)
                $0.image = UIImage(named: "ic_mic")?.withRenderingMode(.alwaysTemplate)
//                $0.setSize(CGSize(width: 36, height: 36), animated: false)
                
                $0.imageView?.backgroundColor = UIColor(white: 1, alpha: 0.1)
                $0.contentEdgeInsets = UIEdgeInsets(top: 2, left: 2, bottom: 2, right: 2)
                $0.setSize(CGSize(width: 38, height: 38), animated: false)
                $0.image = #imageLiteral(resourceName: "ic_mic")
                $0.title = nil
                $0.imageView?.layer.cornerRadius = 18
                
            }.onTouchUpInside { _ in
                print("Item Tapped")
//                self.needContext = false
//                self.view.makeToast("已开启新的对话",position: .center)
                
                // First way to listen to recording through callbacks
                self.voiceOverlayController.start(on: self, textHandler: { (text, final, extraInfo) in
                  print("callback: getting \(String(describing: text))")
                  print("callback: is it final? \(String(describing: final))")
                  
                  if final {
                    // here can process the result to post in a result screen
                    Timer.scheduledTimer(withTimeInterval: 1.5, repeats: false, block: { (_) in
                      let myString = text
                      let myAttribute = [ NSAttributedString.Key.foregroundColor: UIColor.red ]
                      let myAttrString = NSAttributedString(string: myString, attributes: myAttribute)
                      
                      self.voiceOverlayController.settings.resultScreenText = myAttrString
                      self.voiceOverlayController.settings.layout.resultScreen.titleProcessed = "BLA BLA"
                    })
                  }
                }, errorHandler: { (error) in
                  print("callback: error \(String(describing: error))")
                }, resultScreenHandler: { (text) in
                  print("Result Screen: \(text)")
                }
                )
                
            }
        
       
        
//
        messageInputBar.setLeftStackViewWidthConstant(to: 38, animated: true)
        messageInputBar.setStackViewItems([refresh], forStack: .left, animated: false)
        
        
        messageInputBar.setRightStackViewWidthConstant(to: 36, animated: false)
        
        
        
        configToSendButton()
        
        
        configureInputBarPadding()
        
        
        // This just adds some more flare
        messageInputBar.sendButton
            .onEnabled { item in
                UIView.animate(withDuration: 0.3, animations: {
                    item.imageView?.backgroundColor = .primaryColor
                })
            }.onDisabled { item in
                UIView.animate(withDuration: 0.3, animations: {
                    item.imageView?.backgroundColor = UIColor(white: 1, alpha: 0.1)
                })
            }
    }
    
    
    
    /// The input bar will autosize based on the contained text, but we can add padding to adjust the height or width if necessary
    /// See the InputBar diagram here to visualize how each of these would take effect:
    /// https://raw.githubusercontent.com/MessageKit/MessageKit/master/Assets/InputBarAccessoryViewLayout.png
    private func configureInputBarPadding() {
        // Entire InputBar padding
        messageInputBar.padding.bottom = 8
        
        // or MiddleContentView padding
        messageInputBar.middleContentViewPadding.right = -38
        
        // or InputTextView padding
        messageInputBar.inputTextView.textContainerInset.bottom = 8
    }
    
    
}

// MARK: MessagesDisplayDelegate

extension AdvancedExampleViewController: MessagesDisplayDelegate {
    // MARK: - Text Messages
    
    func textColor(for message: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> UIColor {
        isFromCurrentSender(message: message) ? .white : .darkText
    }
    
    func detectorAttributes(
        for detector: DetectorType,
        and message: MessageType,
        at _: IndexPath) -> [NSAttributedString.Key: Any]
    {
        switch detector {
        case .hashtag, .mention:
            if isFromCurrentSender(message: message) {
                return [.foregroundColor: UIColor.white]
            } else {
                return [.foregroundColor: UIColor.primaryColor]
            }
        default: return MessageLabel.defaultAttributes
        }
    }
    
    func enabledDetectors(for _: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> [DetectorType] {
//        [.url, .address, .phoneNumber, .date, .transitInformation, .mention, .hashtag]
        []
    }
    
    // MARK: - All Messages
    
    func backgroundColor(for message: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> UIColor {
        isFromCurrentSender(message: message) ? .primaryColor : UIColor.white
    }
    
    func messageStyle(for message: MessageType, at indexPath: IndexPath, in _: MessagesCollectionView) -> MessageStyle {
        var corners: UIRectCorner = []
        
        if isFromCurrentSender(message: message) {
            corners.formUnion(.topLeft)
            corners.formUnion(.bottomLeft)
            if !isPreviousMessageSameSender(at: indexPath) {
                corners.formUnion(.topRight)
            }
            if !isNextMessageSameSender(at: indexPath) {
                corners.formUnion(.bottomRight)
            }
        } else {
            corners.formUnion(.topRight)
            corners.formUnion(.bottomRight)
            if !isPreviousMessageSameSender(at: indexPath) {
                corners.formUnion(.topLeft)
            }
            if !isNextMessageSameSender(at: indexPath) {
                corners.formUnion(.bottomLeft)
            }
        }
        
        return .custom { view in
            let radius: CGFloat = 16
            let path = UIBezierPath(
                roundedRect: view.bounds,
                byRoundingCorners: corners,
                cornerRadii: CGSize(width: radius, height: radius))
            let mask = CAShapeLayer()
            mask.path = path.cgPath
            view.layer.mask = mask
        }
    }
    
    func configureAvatarView(
        _ avatarView: AvatarView,
        for message: MessageType,
        at indexPath: IndexPath,
        in _: MessagesCollectionView)
    {

        avatarView.isHidden = true
    }
    
    func configureAccessoryView(_ accessoryView: UIView, for message : MessageType, at index: IndexPath, in _: MessagesCollectionView) {
        //    // Cells are reused, so only add a button here once. For real use you would need to
        //    // ensure any subviews are removed if not needed
        accessoryView.subviews.forEach { $0.removeFromSuperview() }
        accessoryView.backgroundColor = .clear
        
      
        if message.messageId == "0"{
            //欢迎语
            if type == -1{
               
                if StoreManager.getHomeChatDescription() != defaultHomeRoleDescription{
                    //非默认角色才显示还原按钮
                    let button = UIButton()
                    button.setImage(UIImage(systemName: "arrow.uturn.backward"), for: .normal)
                    button.tintColor = UIColor.white
                    accessoryView.addSubview(button)
                    button.snp.makeConstraints { make in
                        make.center.equalTo(accessoryView)
                        make.width.height.equalTo(26)
                    }
                    button.contentEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
                    button.isUserInteractionEnabled = true // respond to accessoryView tap through `MessageCellDelegate`
                    button.layer.cornerRadius = 13
                    button.backgroundColor = .primaryColor
//                    button.layer.borderColor = UIColor.primaryColor
//                    button.layer.borderWidth = 2
                    button.tag = Int(message.messageId)  ?? -1
                    button.addTarget(self, action: #selector(revertRole), for: .touchUpInside)
                }
            }else{
                //置顶
                let button = UIButton()
                button.setImage(UIImage(systemName: "pin"), for: .normal)
                button.tintColor = .white
                accessoryView.addSubview(button)
                button.snp.makeConstraints { make in
                    make.center.equalTo(accessoryView)
                    make.width.height.equalTo(26)
                }
                button.contentEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
                button.isUserInteractionEnabled = true // respond to accessoryView tap through `MessageCellDelegate`
                button.layer.cornerRadius = 13
                button.backgroundColor = .primaryColor
                button.layer.borderColor = UIColor.clear.cgColor
                button.layer.borderWidth = 0
                button.tag = Int(message.messageId)  ?? -1
                button.addTarget(self, action: #selector(pinRole), for: .touchUpInside)
            }
            
        }else if !isFromCurrentSender(message: message){//messageId 就是index
            
            let button = UIButton()
            button.setImage(UIImage(systemName: "ellipsis"), for: .normal)
            button.tintColor = .darkText
            accessoryView.addSubview(button)
            button.snp.makeConstraints { make in
                make.center.equalTo(accessoryView)
                make.width.height.equalTo(24)
            }
            button.contentEdgeInsets = UIEdgeInsets(top: 4, left: 4, bottom: 4, right: 4)
            button.isUserInteractionEnabled = true // respond to accessoryView tap through `MessageCellDelegate`
            button.layer.cornerRadius = 12
            button.backgroundColor = UIColor.white
            button.layer.borderColor = UIColor.clear.cgColor
            button.layer.borderWidth = 0
            button.tag = Int(message.messageId)  ?? -1
            button.addTarget(self, action: #selector(moreOption), for: .touchUpInside)
            
        }
    }
    
    
    @objc
    func revertRole(_ sender: UIButton) {
       
        StoreManager.setHomeChatPrompt(description: "")
        StoreManager.setHomeChatTitle(description: "AI")
        
        StoreManager.setHomeChatDescription(description: defaultHomeRoleDescription)
        SwiftEventBus.post(EVENT_NAME_UPDATE_HOME_ROLE)
        self.view.makeToast("已还原默认角色",position: .center)
        
        print("switchRole option")
    }
    @objc
    func pinRole(_ sender: UIButton) {
                if rolePrompt != ""{
                    StoreManager.setHomeChatPrompt(description: rolePrompt)
                    if let title = navigationItem.title{
                        StoreManager.setHomeChatTitle(description: title)
                    }
        
                    StoreManager.setHomeChatDescription(description: roleDescription)
                    SwiftEventBus.post(EVENT_NAME_UPDATE_HOME_ROLE)
                    self.view.makeToast("已设置为首页默认角色",position: .center)
                }
        print("pinRole option")
    }
    
    @objc
    func stopAnswer(_ sender: UIButton) {
        messageInputBar.sendButton.stopAnimating()
        stopSSE()
        print("more option")
    }
    
    @objc
    func moreOption(_ sender: UIButton) {
        if sender.tag > 0{
            FTPopOverMenu.showForSender(sender: sender,
                                        with: (sender.tag == self.messageList.count - 1) ? (self.synthVM.isSpeaking ? ["复制", "重新回答", "继续回答",StoreManager.isVoiceOpen() ? "关闭跟读" : "开启跟读" , "停止跟读"]:["复制", "重新回答", "继续回答",StoreManager.isVoiceOpen() ? "关闭跟读" : "开启跟读" ]) :["复制" ] ,
                                        menuImageArray: (sender.tag == self.messageList.count - 1) ?(self.synthVM.isSpeaking ? ["ic_copy","ic_reanswer","ic_continue","ic_volume","ic_stop_speaking"]:["ic_copy","ic_reanswer","ic_continue","ic_volume"]) : ["ic_copy"],
                                        popOverPosition: .automatic,
                                        config: self.configWithMenuStyle(),
                                        done: { (selectedIndex) in
                
                
                print("messageId==\(sender.tag)")
                if selectedIndex == 0{
                    if let message = self.getMessage("\(sender.tag)"){
                        let kind = message.kind as MessageKind
                        switch kind
                        {
                        case .text(let messageContent):
                            UIPasteboard.general.string = messageContent
                            self.view.makeToast("复制成功",position: .center)
                        default:
                            print ("whatever")
                        }
                        
                    }
                }else  if selectedIndex == 1{
                    if let questionMessage = self.getMessage("\(sender.tag - 1)"){
                        let kind = questionMessage.kind as MessageKind
                        switch kind
                        {
                        case .text(let messageContent):
                            //                            //移除重试的问题以及答案
                            //                            self.messageList.remove(at: sender.tag)
                            //                            self.messageList.remove(at: (sender.tag-1))
                            self.messageInputBar.inputTextView.text = messageContent
                            self.processInputBar(self.messageInputBar)
                        default:
                            print ("whatever")
                        }
                        
                    }
                }else  if selectedIndex == 2{
                    if let questionMessage = self.getMessage("\(sender.tag - 1)"){
                        let kind = questionMessage.kind as MessageKind
                        switch kind
                        {
                        case .text(let messageContent):
                            //检测语言
                            self.languageRecognizer.processString(messageContent)
                            var localId = "zh-CN"
                            if let dominantLanguage = self.languageRecognizer.dominantLanguage {
                                localId = dominantLanguage.rawValue
                                print("language=\(localId)")
                                
                            }
                            let  continueString = continueDict[localId]
                            print("continueString=\(continueString)")
                            self.messageInputBar.inputTextView.text = continueString
                            self.processInputBar(self.messageInputBar)
                        default:
                            print ("whatever")
                        }
                        
                        
                    }
                }else  if selectedIndex == 3{
                    
                    if StoreManager.isVoiceOpen(){
                        //关闭
                        StoreManager.setVoiceOpen(isOpen: false)
                    }else{
                        //打开跟读
                        StoreManager.setVoiceOpen(isOpen: true)
                        
                        if let questionMessage = self.messageList.last{
                            let kind = questionMessage.kind as MessageKind
                            switch kind
                            {
                            case .text(let messageContent):
                                self.synthVM.speak()
                                self.synthVM.addTextToSpeech(text: messageContent)
                            default:
                                print ("whatever")
                            }
                            
                            
                        }
                        
                        
                    }
                }else  if selectedIndex == 4{
                    
                    self.synthVM.stop()
                }
                print(selectedIndex)
                
            },
                                        cancel: {
                print("cancel")
            })
        }
        print("more option")
        
    }
    
    func getMessage(_ messageId: String) -> MockMessage?{
        var targetMessage: MockMessage?
        for message in self.messageList {
            if message.messageId == messageId{
                targetMessage = message
            }
        }
        return targetMessage
    }
    
    func configWithMenuStyle() -> FTConfiguration {
        let config = FTConfiguration()
        
        config.backgoundTintColor = primaryBackgroundColor
                    config.borderColor = primaryBackgroundColor
                    config.menuWidth = 150
                    config.menuSeparatorColor = primaryDarkBackgroundColor
                    config.menuRowHeight = 50
                    config.cornerRadius = 20
                    config.textColor = UIColor.white
        
        return config
    }
    
    
    
    
}

// MARK: MessagesLayoutDelegate

extension AdvancedExampleViewController: MessagesLayoutDelegate {
    func cellTopLabelHeight(for _: MessageType, at indexPath: IndexPath, in _: MessagesCollectionView) -> CGFloat {
        if isTimeLabelVisible(at: indexPath) {
            return 18
        }
        return 0
    }
    
    func messageTopLabelHeight(for message: MessageType, at indexPath: IndexPath, in _: MessagesCollectionView) -> CGFloat {
        if isFromCurrentSender(message: message) {
            return !isPreviousMessageSameSender(at: indexPath) ? 20 : 0
        } else {
            return !isPreviousMessageSameSender(at: indexPath) ? (20 + outgoingAvatarOverlap) : 0
        }
    }
    
    func messageBottomLabelHeight(for message: MessageType, at indexPath: IndexPath, in _: MessagesCollectionView) -> CGFloat {
        (!isNextMessageSameSender(at: indexPath) && isFromCurrentSender(message: message)) ? 16 : 0
    }
}

